#ifndef _EXAMPLE_HPP_
#define _EXAMPLE_HPP_

#include <memory>
#include <string>
#include <vector>
#include "cJSON.h"

class JsonData {
public:
	std::string    String;
	int            Number    = 0;
	double         Float     = 0.0;
	bool           Boolean   = false;
	std::nullptr_t NullValue = nullptr;

	// Array element definition
	struct ArrayElement {
		enum class Type { String, Int, Bool, Object, Array };
		Type        type;
		std::string StringValue;
		int         IntValue  = 0;
		bool        BoolValue = false;

		struct Object {
			std::string NestedObject;
		};
		Object ObjectValue;

		struct Array {
			std::vector<int> Elements;
		};
		Array ArrayValue;

		ArrayElement() = default;
		ArrayElement(std::string s) : type(Type::String), StringValue(std::move(s)) {}
		ArrayElement(int i) : type(Type::Int), IntValue(i) {}
		ArrayElement(bool b) : type(Type::Bool), BoolValue(b) {}
		ArrayElement(const Object &obj) : type(Type::Object), ObjectValue(obj) {}
		ArrayElement(const Array &arr) : type(Type::Array), ArrayValue(arr) {}
	};
	std::vector<ArrayElement> Array;

	// Object definition
	struct Object {
		std::string Key;

		struct NestedArrayElement {
			int  Id     = 0;
			bool Active = false;
		};
		std::vector<NestedArrayElement> NestedArray;
	};
	Object Object;

	std::vector<ArrayElement> EmptyArray;

	struct EmptyObject {};
	EmptyObject EmptyObject;

	// Mixed types definition
	struct MixedElement {
		enum class Type { Null, String, Int, Bool, Object };
		Type        type = Type::Null;
		std::string StringValue;
		int         IntValue  = 0;
		bool        BoolValue = false;

		struct ComplexObject {
			std::vector<MixedElement> Complex;
		};
		std::shared_ptr<ComplexObject> ObjectValue;

		MixedElement() = default;
		MixedElement(std::nullptr_t) : type(Type::Null) {}
		MixedElement(std::string s) : type(Type::String), StringValue(std::move(s)) {}
		MixedElement(int i) : type(Type::Int), IntValue(i) {}
		MixedElement(bool b) : type(Type::Bool), BoolValue(b) {}
		MixedElement(std::shared_ptr<ComplexObject> obj) : type(Type::Object), ObjectValue(std::move(obj)) {}
	};
	std::vector<MixedElement> MixedTypes;
};
#endif // _EXAMPLE_HPP_
